package com.xusheng.cli.tools;

import java.util.*;
import java.util.Map.Entry;
import java.util.function.Consumer;
import java.util.function.Function;

import static java.util.Collections.singletonList;

/**
 * 构造Map内容的便利类，可以用Fluent的调用方式构造一个Map，模式为Putif.start() ... .get();
 *
 * @author zhy
 */
@SuppressWarnings("unused")
public final class Putif {
	
    private final Map<String, Object> map;

    private Putif(Map<String, Object> map) {
        this.map = map == null ? new HashMap<>() : map;
    }

    /**
     * 开始一个新Map。
     */
    public static Putif start() {
        return new Putif(null);
    }

    /**
     * 包装传入的Map，如果其为null，开始一个新Map。
     */
    public static Putif start(Map<String, Object> map) {
        return new Putif(map);
    }

    /**
     * 获取目前填好的Map。
     */
    public Map<String, Object> get() {
        return map;
    }

    /**
     * 将目前填好的Map放到一个单点集中返回。
     */
    public List<Map<String, Object>> singleton() {
        return singletonList(map);
    }

    /**
     * 获取目前填好的Map，如果其为空，返回null。
     */
    public Map<String, Object> nullIfEmpty() {
        return map.isEmpty() ? null : map;
    }

    /**
     * 将传入map的数据添加到本map中，已存在的key不变。
     */
    public Putif append(Map<String, Object> map) {
        if (map != null && map != this.map && !map.isEmpty()) {
            for (Entry<String, Object> entry : map.entrySet()) {
                this.map.putIfAbsent(entry.getKey(), entry.getValue());
            }
        }
        return this;
    }

    /**
     * 不论value是否为null，加到map的指定key下。
     */
    public Putif anyway(String key, Object value) {
        map.put(key, value);
        return this;
    }

    /**
     * 如果值不为null，将其加到map的指定key下。
     */
    public Putif notNull(String key, Object value) {
        if (value != null) {
            map.put(key, value);
        }
        return this;
    }

    /**
     * 如果字符串非null非空，加到map的指定key下。
     */
    public Putif notEmpty(String key, String value) {
        if (Utils.isNotEmpty(value)) {
            map.put(key, value);
        }
        return this;
    }

    /**
     * 如果集合非null非空，加到map的指定key下。
     */
    public <T> Putif notEmpty(String key, Collection<T> value) {
        if (Utils.isNotEmpty(value)) {
            map.put(key, value);
        }
        return this;
    }

    /**
     * 如果传入map非null非空，加到map的指定key下。
     */
    public <K, V> Putif notEmpty(String key, Map<K, V> value) {
        if (Utils.isNotEmpty(value)) {
            map.put(key, value);
        }
        return this;
    }

    /**
     * 如果value为正数，加到map的指定key下。
     */
    public Putif positive(String key, Integer value) {
        if (value != null && value > 0) {
            map.put(key, value);
        }
        return this;
    }

    /**
     * 如果value为正数，加到map的指定key下。
     */
    public Putif positive(String key, int value) {
        if (value > 0) {
            map.put(key, value);
        }
        return this;
    }

    /**
     * 如果value非负，加到map的指定key下。
     */
    public Putif nonNegative(String key, Integer value) {
        if (value != null && value >= 0) {
            map.put(key, value);
        }
        return this;
    }

    /**
     * 如果value非负，加到map的指定key下。
     */
    public Putif nonNegative(String key, int value) {
        if (value >= 0) {
            map.put(key, value);
        }
        return this;
    }

    /**
     * 如果value为正，加到map的指定key下。
     */
    public Putif positive(String key, long value) {
        if (value > 0) {
            map.put(key, value);
        }
        return this;
    }

    /**
     * 如果value为正，加到map的指定key下。
     */
    public Putif positive(String key, double value) {
        if (value > 0) {
            map.put(key, value);
        }
        return this;
    }

    /**
     * 如果value非零，加到map的指定key下。
     */
    public Putif notZero(String key, double value) {
        if (value != 0) {
            map.put(key, value);
        }
        return this;
    }

    /**
     * 如果value为true，加到map的指定key下。
     */
    public Putif truth(String key, boolean value) {
        if (value) {
            map.put(key, true);
        }
        return this;
    }

    /**
     * 如果coll非空，对其每个元素应用func进行变换，结果如果非null，放到一个列表中。
     * 最终列表如果非空，加到map的指定key下。
     */
    public <T, R> Putif each(String key, Collection<T> coll, Function<T, R> func) {
        if (coll == null || coll.isEmpty()) {
            return this;
        }
        List<R> list = new ArrayList<>();
        for (T obj : coll) {
            R result = func.apply(obj);
            if (result != null) {
                list.add(result);
            }
        }
        if (!list.isEmpty()) {
            map.put(key, list);
        }
        return this;
    }

    /**
     * 如果传入map非空，对其每一项应用func进行变换，结果如果非null，放到一个列表中。
     * 最终列表如果非空，加到map的指定key下。
     */
    public <K, V, R> Putif each(String key, Map<K, V> map, Function<Entry<K, V>, R> func) {
        if (map == null || map.isEmpty()) {
            return this;
        }
        List<R> list = new ArrayList<>();
        for (Entry<K, V> entry : map.entrySet()) {
            R result = func.apply(entry);
            if (result != null) {
                list.add(result);
            }
        }
        if (!list.isEmpty()) {
            this.map.put(key, list);
        }
        return this;
    }

    /**
     * 如果条件成立，调用consumer，把当前实例传给它，让它继续填写map。
     */
    public Putif cond(boolean condition, Consumer<Putif> consumer) {
        if (condition) {
            consumer.accept(this);
        }
        return this;
    }

}
